package com.media.api;

import com.alibaba.fastjson.JSON;
import com.media.mapper.MediaMapper;
import com.media.model.Media;
import com.media.model.Publish;
import com.base.model.R;
import com.media.model.Tag;
import com.media.model.dto.PieDataDto;
import com.media.service.MediaService;
import com.base.utils.VideoUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.security.SecurityUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Author: Lenovo
 * @Description: TODO
 * @DateTime: 2023/9/13 14:24
 **/
@Api(tags = "视频接口")
@RestController
@RequestMapping("/media")
public class MediaController {


    @Autowired
    private MediaMapper mediaMapper;

    @Autowired
    private MediaService mediaService;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String REDIS_MEDIA_PREFIX = "media_";


    /**
     * 上传视频文件，视频封面，视频信息
     *
     * @param media    视频文件
     * @param cover    封面文件
     * @param title    标题
     * @param category 分类,用数字标识,暂定1代表科普类,2代表搞笑类,3代表纪录片
     * @return 返回字符串
     * todo:需要同时传输tag的json数组,但目前遇到的问题是文件需要使用body以form-data传输,就不能使用raw来传输json,网上说可以使用
     */
    @ApiOperation("用户上传视频")
    @PostMapping(value = "/upload")
    @PreAuthorize("hasAuthority('uploadMedia')")
    public R<String> uploadMedia(@RequestParam("media") MultipartFile media, @RequestParam("cover") MultipartFile cover, @RequestParam("title") String title, @RequestParam("category") int category, @RequestParam("tags") String tags) {
        VideoUtil videoUtil = new VideoUtil();
        Publish publish = new Publish();
        //1.从SpringSecurity中获取用户Id,用户姓名
        //先固定写死，后面再从SpringSecurity中获取.
        Integer id = 1;
        publish.setUploader(id);
        publish.setUploaderName("小何");
        //2.填充视频发布信息
        publish.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        publish.setTitle(title);
        publish.setCategory(category);
        publish.setUploadTime(new Timestamp(System.currentTimeMillis()));
        publish.setSize(media.getSize());
        publish.setTags(tags);

        //3.生成临时文件，上传到Minio中.因为现在的文件为网络传输,如果不生成临时文件，则无法获取文件路径，上传到文件服务器上.
        String originalMediaFilename = media.getOriginalFilename();
        String originalCoverFilename = cover.getOriginalFilename();
        File tempFileMedia = null;
        File tempFileCover = null;
        try {
            //获取文件拓展名
            String extensionMedia = originalMediaFilename.substring(originalMediaFilename.lastIndexOf('.'));
            String extensionCover = originalCoverFilename.substring(originalCoverFilename.lastIndexOf('.'));
            //创建临时文件,使用UUID作为文件前缀，防止文件名重复。后缀使用原文件的后缀。
            tempFileMedia = File.createTempFile(UUID.randomUUID().toString().replace("-", ""), extensionMedia);
            tempFileCover = File.createTempFile(UUID.randomUUID().toString().replace("-", ""), extensionCover);
            //将源文件拷贝到临时文件
            media.transferTo(tempFileMedia);
            cover.transferTo(tempFileCover);
            //使用工具类调用ffmpeg获取视频时长，以此填充时长字段。
            String video_time = videoUtil.get_video_time(tempFileMedia.getAbsolutePath());
            publish.setDuration(video_time);
        } catch (IOException e) {
            //当存在异常时将临时文件删除，防止临时文件占用过多硬盘空间
            videoUtil.deleteFile(tempFileCover, tempFileMedia);
            return R.error("生成临时文件失败.");
        }

        //获取临时文件的绝对路径
        String localFilePathMedia = tempFileMedia.getAbsolutePath();
        String localFilePathCover = tempFileCover.getAbsolutePath();
        return mediaService.uploadMedia(localFilePathMedia, localFilePathCover, publish, tags);
    }

    /**
     * 下架视频，即将视频状态修改为0
     *
     * @param mediaId 视频Id
     * @return 返回字符串
     */
    @ApiOperation("审核员或管理员下架视频")
    @DeleteMapping(value = "/disable/{mediaId}")
    @PreAuthorize("hasAuthority('disableMedia')")
    public R<String> disableMedia(@PathVariable("mediaId") String mediaId) {
        return mediaService.disableMedia(mediaId);
    }

    @ApiOperation("审核员或管理员恢复下架视频")
    @PutMapping(value = "/shelve/{mediaId}")
    @PreAuthorize("hasAuthority('recoverMedia')")
    public R<String> shelveMedia(@PathVariable("mediaId") String mediaId) {
        return mediaService.shelveMedia(mediaId);
    }

    /**
     * 获取所有的视频信息
     * page 页码
     * pageSize 页面大小
     *
     * @return 返回视频信息
     */
    @ApiOperation("分页获取视频信息")
    @PostMapping(value = "/listMedia/{page}/{pageSize}")
    public R<List<Media>> listMedia(@PathVariable Integer page, @PathVariable Integer pageSize, @RequestBody Media media) {
        return mediaService.listMedia(page, pageSize, media);
    }

    @ApiOperation("分页获取视频信息——视频修改页面使用")
    @PostMapping(value = "/listMediaNeedAuthentication/{page}/{pageSize}")
    @PreAuthorize("hasAuthority('listMedia')")
    public R<List<Media>> listMediaNeedAuthentication(@PathVariable Integer page, @PathVariable Integer pageSize, @RequestBody Media media) {
        return mediaService.listMedia(page, pageSize, media);
    }


//    @PostMapping(value = "/auditAll")
//    public R<String> auditAll(){
//        return mediaService.auditAll();
//    }


    @PutMapping(value = "/updateMedia")
    @PreAuthorize("hasAuthority('updateMedia')")
    public R<String> updateMedia(@RequestBody Media media) {
        return mediaService.updateMedia(media);
    }

//    /**
//     * 视频转码
//     * @param MD5 文件MD5值
//     * @return 提示信息
//     */
//    @PostMapping(value = "/transcode")
//    public R<String> transcode(@RequestParam("suffix")String suffix,@RequestParam("MD5")String MD5){
//        return mediaService.transcode(MD5,suffix);
//    }

    /**
     * 通过视频Id获取视频数据
     *
     * @param videoId
     * @return
     */
    @GetMapping(value = "/video/{videoId}")
    public R<Media> getVideoByVideoId(@PathVariable String videoId) {
        if (redisTemplate.hasKey(REDIS_MEDIA_PREFIX)) {
            String json = (String) redisTemplate.opsForValue().get(REDIS_MEDIA_PREFIX + videoId);
            return R.success(JSON.parseObject(json, Media.class));
        }
        R<Media> videoByVideoId = mediaService.getVideoByVideoId(videoId);
        redisTemplate.opsForValue().set(REDIS_MEDIA_PREFIX + videoId, JSON.toJSONString(videoByVideoId.getData()));
        return videoByVideoId;
    }

    /**
     * 获取前台绘制饼图所需数据
     */
    @PreAuthorize("hasAuthority('getPieData')")
    @GetMapping(value = "/getPieData")
    public R<List<PieDataDto>> getPieData() {
        List<PieDataDto> pieData = mediaMapper.getPieData();
        return R.success(pieData);
    }
}
